package com.jiajia.arraylist.approve;


/**
 * @author : zjj
 * @date : 2021/1/12 15:27
 */
public class MyArrayList<E> {

    /**
     * 元素的数量
     */
    private int size;
    /**
     * 所有元素
     */
    private E[] elements;

    /**
     * 默认容量大小
     */
    private static final int DEFAULT_CAPACITY = 10 ;
    /**
     * 元素没找到索引
     */
    private static final int ELEMENT_NOT_FOUNT = -1;

    public MyArrayList(int capacity){
        capacity = (capacity < DEFAULT_CAPACITY) ? DEFAULT_CAPACITY : capacity;
        this.elements = (E[])new Object[capacity];
    }

    public MyArrayList(){
        this(DEFAULT_CAPACITY);
    }

    /**
     * 清除所有元素
     */
    public void clear(){
        for (int i = 0; i < size; i++) {
            elements[i] = null;
        }
        this.size = 0;
    }

    /**
     * 元素的数量
     * @return  元素的数量 size
     */
    public int size(){
        return size;
    }

    /**
     * 是否为空
     * @return  结果
     */
    public boolean isEmpty(){
        return size == 0;
    }

    public boolean contains(E element){
        return indexOf(element) != ELEMENT_NOT_FOUNT;
    }

    /**
     * 添加元素到尾部
     * @param element   元素
     */
    public void add(E element){
       /* elements[size] = element;
        size++ ;*/
        // 可以两句合成一句，elements[size++] = element ;
        add(size,element);
    }

    /**
     * 获取index位置的元素
     * @param index     索引
     * @return          元素的位置
     */
    public E get(int index){
        rangeCheck(index);
        return elements[index];
    }

    /**
     * 设置元素的位置
     * @param index     元素的位置
     * @param element   元素
     * @return          原来该位置的值
     */
    public E set(int index,E element){
        rangeCheck(index);
        E old = elements[index];
        elements[index] = element;
        return old;
    }

    /**
     * 在索引位置设置元素
     * @param index     索引位置
     * @param element   元素
     */
    public void add(int index,E element){
        rangeCheckForAdd(index);

        ensureCapacity(size+1);

        for (int i = size; i > index; i--) {
            elements[i] = elements[i - 1];
        }
        elements[index] = element;
        size++;

    }

    /**
     * 删除索引位置的元素
     * 思路：将要索引位置后面的数据都往前移动一位，索引位置的数据就被删除了
     * @param index 索引
     * @return      删除的元素
     */
    public E remove(int index){
        rangeCheck(index);
        // 被删除的值
        E old = elements[index];
        // 移动删除数据后面的数据
        for (int i = (index + 1) ; i< size ;i++){
            elements[i-1] = elements[i] ;
        }
        size--;
        elements[size] = null;
        return old;
    }

    /**
     * 查看元素的索引,没找到返回-1
     * @param element   元素
     * @return          元素的索引
     */
    public int indexOf(E element){
        if(null == element){
            for (int i = 0; i < size; i++) {
                if(null == elements[i]){
                    return i;
                }
            }
        }else {
            for(int i=0; i<size; i++){
                if(elements[i].equals(element)){
                    return i;
                }
            }
        }
        return ELEMENT_NOT_FOUNT;
    }

    /**
     * 扩容机制
     * 当期望容量大于现有容量的时候，就会进行扩容，我们这里是扩大为原来的1.5倍
     * @param capacity  期望容量
     */
    private void ensureCapacity(int capacity){
        int oldCapacity = elements.length;
        if(oldCapacity >= capacity){
            return;
        }
        int newCapacity  = oldCapacity + (oldCapacity>>1);
        E[] newElements = (E[])new Object[newCapacity];
        for (int i=0;i<size;i++){
            newElements[i] = elements[i];
        }
        elements = newElements;

        System.out.println("旧容量为：" + oldCapacity +"，扩容为：" + newCapacity);

    }

    /**
     * 索引范围检查
     * @param index 索引值
     */
    public void rangeCheck(int index){
        if(index < 0 || index >= size){
            outOfBound(index);
        }
    }

    /**
     * 添加方法索引范围检查
     * @param index 索引值
     */
    public void rangeCheckForAdd(int index){
        if(index < 0 || index > size){
            outOfBound(index);
        }
    }

    public void outOfBound(int index){
        throw new IndexOutOfBoundsException("索引越界异常：index" + index + ",size:" + size);
    }

    @Override
    public String toString() {

        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("size:" + size + ",[");
        for (int i=0;i<size ;i++){
            if(i!= 0){
                stringBuilder.append(",");
            }
            stringBuilder.append(elements[i]);
        }
        stringBuilder.append("]");
        return stringBuilder.toString();

    }
}
